package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.cache.RedisCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.pattern.DeliveryStrategy;
import com.atguigu.tingshu.user.pattern.factory.DeliveryStrategyFactory;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;
	@Autowired
	private WxMaService wxMaService;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;
	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;
	@Autowired
	private AlbumFeignClient albumFeignClient;
	@Autowired
	private UserVipServiceMapper userVipServiceMapper;
	@Autowired
	private UserPaidTrackService userPaidTrackService;
	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Override
	public Map<String, String> wxLogin(String code) {
		try {
			//1. 通过临时凭据code+应用id+应用秘钥 调用微信接口 获取当前微信账户唯一标识: openId
			//1.1 微信账户信息业务类
			WxMaUserService wxMaUserService = wxMaService.getUserService();
			//1.2 获取会话信息
			WxMaJscode2SessionResult sessionInfo = wxMaUserService.getSessionInfo(code);
			//1.3 获取微信账号唯一标识
			String openid = sessionInfo.getOpenid();
			//通过openid查询数据库中是否有此用户
			LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(UserInfo::getWxOpenId,openid);
			UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);
			//如果微信账户首次注册,则新增用户记录,并初始化账户
			if(userInfo == null){
				//新增用户记录,绑定微信账户唯一标识
				userInfo = new UserInfo();
				userInfo.setWxOpenId(openid);
				userInfo.setNickname(IdUtil.nanoId()); //随机生成用户昵称
				userInfo.setAvatarUrl("http://192.168.200.6:9000/tingshu/2024-04-02/0e9cfe8a-9866-4bc5-9a7f-164ed5ef5938.png"); // 设置默认头像
				userInfoMapper.insert(userInfo);

				// 为当前注册用户初始化账户记录
				Map<String,Object> map = new HashMap<>();
				map.put("userId",userInfo.getId());
				map.put("title","新用户注册福利100元优惠券");
				map.put("amount", BigDecimal.valueOf(100));
				map.put("orderNo","zs" + IdUtil.getSnowflakeNextId());
				//发送mq消息  采用MQ可靠性消息队列实现消息最终一致
				rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_REGISTER,map);

			}
			//基于当前用户信息生成令牌
			String token = IdUtil.randomUUID();
			//将用户信息存入到redis中 有效期七天
			String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
			UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
			redisTemplate.opsForValue().set(userLoginKey,userInfoVo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);

			return Map.of("token",token);
		} catch (WxErrorException e) {
			log.error("微信用户登录失败",e);
			throw new GuiguException(500,"微信用户登录失败");
		}
	}

	@Override
	@RedisCache(prefix ="user:")
	public UserInfoVo getUserInfo(Long userId) {
		UserInfo userInfo = userInfoMapper.selectById(userId);
		if(userInfo != null){
			UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
			return userInfoVo;
		}
		return null;
	}

	/**
	 * 更新用户信息方法
	 * 只允许修改昵称头像
	 * @param userInfoVo
	 */
	@Override
	public void updateUser(UserInfoVo userInfoVo) {
		if(userInfoVo == null){
			System.out.println("userInfoVo实体类为null");
			return;
		}
		UserInfo userInfo = new UserInfo();
		userInfo.setId(AuthContextHolder.getUserId());
		userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());//修改头像
		userInfo.setNickname(userInfoVo.getNickname());//修改昵称

		userInfoMapper.updateById(userInfo);
	}

	/**
	 * 提交需要检查购买状态声音ID列表，响应每个声音购买状态
	 * 是否显示付费标识，isShowPiadMark=true，则显示付费标识
	 * @param userId                        用户ID
	 * @param albumId                       专辑ID
	 * @param needCheckPayStatusTrackIdList 待检查购买状态声音ID列表
	 * @return
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> needCheckPayStatusTrackIdList) {
		Map<Long, Integer> map = new HashMap<>();
		//检查该用户购买的专辑列表中是否包含此专辑
		Long count = userPaidAlbumMapper.selectCount(
				new LambdaQueryWrapper<UserPaidAlbum>()
						.eq(UserPaidAlbum::getUserId, userId)
						.eq(UserPaidAlbum::getAlbumId, albumId)
		);
		//如果count > 0说明该用户已购买此专辑
		if(count > 0){
			for (Long aLong : needCheckPayStatusTrackIdList) {
				map.put(aLong,1);
			}
			return map;
		}
		//查询用户购买的此专辑下的声音列表
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(
				new LambdaQueryWrapper<UserPaidTrack>()
						.eq(UserPaidTrack::getUserId, userId)
						.eq(UserPaidTrack::getAlbumId,albumId)
						.select(UserPaidTrack::getTrackId)
		);
		if(CollectionUtils.isEmpty(userPaidTrackList)){
			//如果用户没有购买此专辑中的音频
			for (Long aLong : needCheckPayStatusTrackIdList) {
				map.put(aLong,0);
			}
			return map;
		}
		//将用户购买的音频与needCheckPayStatusTrackIdList中的trackId进行比对
		List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
		for (Long aLong : needCheckPayStatusTrackIdList) {
			if(userPaidTrackIdList.contains(aLong)){
				map.put(aLong,1);
			}else{
				map.put(aLong,0);
			}
		}
		return map;
	}

	/**
	 * 判断当前用户是否购买过指定专辑
	 *
	 * @param albumId
	 * @return
	 */
	@Override
	public Boolean isPaidAlbum(Long userId, Long albumId) {
		Long count = userPaidAlbumMapper.selectCount(
				new LambdaQueryWrapper<UserPaidAlbum>()
						.eq(UserPaidAlbum::getAlbumId, albumId)
						.eq(UserPaidAlbum::getUserId, userId)
		);
		return count > 0;
//		return count > 0 ? true:false;
	}


	/**
	 * 查询当前用户某个专辑下已购声音ID列表
	 * @param albumId
	 * @return
	 */
	@Override
	public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
		List<UserPaidTrack> paidTrackList = userPaidTrackMapper.selectList(
				new LambdaQueryWrapper<UserPaidTrack>()
						.eq(UserPaidTrack::getUserId, userId)
						.eq(UserPaidTrack::getAlbumId, albumId)
						.select(UserPaidTrack::getTrackId)
		);
		if(!CollectionUtils.isEmpty(paidTrackList)){
			List<Long> list = paidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
			return list;
		}
		return null;
	}


	@Autowired
	private DeliveryStrategyFactory deliveryStrategyFactory;
	/**
	 * 用户支付成功后，虚拟物品发货
	 * @param vo
	 * @return
	 */
	@Override
	public void savePaidRecord(UserPaidRecordVo vo) {
		// 策略模式+工厂模式
		//根据类型从工厂中获取到对应的策略实现类对象
		DeliveryStrategy deliveryStrategy = deliveryStrategyFactory.getDeliveryStrategy(vo.getItemType());
		//调用策略实现类对象对应的发货业务
		deliveryStrategy.delivery(vo);



//		//获取到购买的项目类型 1001-专辑 1002-声音 1003-vip会员
//		String itemType = vo.getItemType();
//		//获取订单号
//		String orderNo = vo.getOrderNo();
//
//		if(SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(itemType)){
//			//专辑
//			//根据订单号从用户购买记录中查询,判断是否已经存在此记录
//			Long count = userPaidAlbumMapper.selectCount(
//					new LambdaQueryWrapper<UserPaidAlbum>()
//							.eq(UserPaidAlbum::getOrderNo, orderNo)
//			);
//			if(count > 0){
//				log.info("已存在该订单:{}的已购专辑记录", orderNo);
//				return;
//			}
//			//如果不存在该记录则封装对象将记录存入数据库中
//			UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
//			userPaidAlbum.setOrderNo(orderNo);
//			userPaidAlbum.setUserId(vo.getUserId());
//			userPaidAlbum.setAlbumId(vo.getItemIdList().get(0));
//			userPaidAlbumMapper.insert(userPaidAlbum);
//		}else if(SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(itemType)){
//			//声音
//			//根据订单号从数据库中查询是否已有购买记录
//			Long count = userPaidTrackMapper.selectCount(
//					new LambdaQueryWrapper<UserPaidTrack>()
//							.eq(UserPaidTrack::getOrderNo,orderNo)
//			);
//			if(count > 0){
//				log.info("已存在该订单:{}的已购声音记录", orderNo);
//				return;
//			}
//			//封装购买声音记录对象,将记录存入到数据库中
//			List<Long> itemIdList = vo.getItemIdList();
//			if(!CollectionUtils.isEmpty(itemIdList)){
//				//调用远程服务从声音对象中获取专辑id
//				TrackInfo trackInfo = albumFeignClient.getTrackInfo(itemIdList.get(0)).getData();
//				Long albumId = trackInfo.getAlbumId();
//				Assert.notNull(trackInfo,"声音{}信息为空",itemIdList.get(0));
//				List<UserPaidTrack> list = new ArrayList<>();
//				for (Long item : itemIdList) {
//					UserPaidTrack userPaidTrack = new UserPaidTrack();
//					userPaidTrack.setOrderNo(orderNo);
//					userPaidTrack.setUserId(vo.getUserId());
//					userPaidTrack.setAlbumId(albumId);
//					userPaidTrack.setTrackId(item);
//					list.add(userPaidTrack);
//				}
//				//批量插入
//				userPaidTrackService.saveBatch(list);
//			}
//		}else if(SystemConstant.ORDER_ITEM_TYPE_VIP.equals(itemType)){
//			//VIP
//			//根据订单号从用户购买记录中进行查询是否有此记录
//			Long count = userVipServiceMapper.selectCount(
//					new LambdaQueryWrapper<UserVipService>()
//							.eq(UserVipService::getOrderNo, orderNo)
//			);
//			if(count > 0){
//				log.info("已存在该订单:{}的已购VIP记录", orderNo);
//				return;
//			}
//			//判断当前用户是否是会员
//			UserInfoVo userInfoVo = getUserInfo(vo.getUserId());
//			Boolean isVIP = false;
//			if(userInfoVo.getIsVip().intValue()==1 && userInfoVo.getVipExpireTime().after(new Date())){
//				isVIP = true;
//			}
//			//获取用户购买的套餐
//			VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vo.getItemIdList().get(0));
//			//获取套餐的服务月数
//			Integer serviceMonth = vipServiceConfig.getServiceMonth();
//			//计算vip到期时间
//			Date startTime;
//			Date expireTime;
//			if(isVIP){
//				//如果本身就是会员
//				startTime = DateUtil.offsetDay(userInfoVo.getVipExpireTime(),1);
//				expireTime = DateUtil.offsetMonth(startTime,serviceMonth);
//			}else{
//				//如果本来不是会员
//				startTime = new Date();
//				expireTime = DateUtil.offsetMonth(new Date(), serviceMonth);
//			}
//			//如果不存在此记录则声明对象并存入数据库中
//			UserVipService userVipService = new UserVipService();
//			userVipService.setOrderNo(orderNo);
//			userVipService.setUserId(vo.getUserId());
//			userVipService.setStartTime(startTime);
//			userVipService.setExpireTime(expireTime);
////			userVipService.setIsAutoRenew();
////			userVipService.setNextRenewTime();
//			userVipServiceMapper.insert(userVipService);
//			//更新用户信息
//			userInfoVo.setIsVip(1);
//			userInfoVo.setVipExpireTime(expireTime);
//			UserInfo userInfo = BeanUtil.copyProperties(userInfoVo, UserInfo.class);
//			userInfoMapper.updateById(userInfo);
//		}
	}

	/**
	 * 清理过期会员
	 * @param date
	 */
	@Override
	public void updateUserVipStatus(Date date) {
		//查询出vip过期的用户列表
		List<UserInfo> userInfoList = userInfoMapper.selectList(
				new LambdaQueryWrapper<UserInfo>()
						.eq(UserInfo::getIsVip, 1)
						.lt(UserInfo::getVipExpireTime, date)
		);
		//更新vip过期用户的vip标识
		userInfoList.stream().forEach(u -> u.setIsVip(0));
		this.updateBatchById(userInfoList);
	}
}
